﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.IO;
using System.Text;
using IMIForUnity;

namespace IMIForUnity
{
    public class ImiGestureWrapper
    {
        public const int IMI_USER_HANDCURSOR_COUNT = 20;
#if UNITY_ANDROID && !UNITY_EDITOR
        private const string filePath = "IminectUnity";

#else
        private const string filePath = "ImiUnitySDK";
#endif

        //#if UNITY_ANDROID && !UNITY_EDITOR
        //private const string filePath = "libimigesture";
        //private const string filePath = "ImiUnitySDK";
        //#else
        //private const string filePath = "IminectUnity";
        //#endif
        //private const string filePath2 = "IminectUnity";


        public enum ImiInteractionRegionMode
        {
            IMI_INTERACTION_REGION_MODE_NORMAL = 0,             // Normal interaction reigion mode,width equals height widht/height = 1
            IMI_INTERACTION_REGION_MODE_LANDSCAPE,              // Landscape interaction region mode,wide screen e.g. height/width = 0.5625(1080/1920)
            IMI_INTERACTION_REGION_MODE_PORTRAIT,               // Portrait interaction region mode,tall and narrow screen e.g. width/height = 0.5625}
        }

        public enum ImiHandType
        {
            IMI_HAND_TYPE_LEFT = 0,                             // Left hand
            IMI_HAND_TYPE_RIGHT,                                // Right hand
        }

        public enum ImiHandCursorState
        {
            IMI_HAND_CURSOR_STATE_NONE = 0x00,          // Undefined state
            IMI_HAND_CURSOR_STATE_INTERACTIVE = 0x01,           // Hand is in interaction region
            IMI_HAND_CURSOR_STATE_PRIMARY = 0x02,           // Primary hand for user used when both hands are interactive
            IMI_HAND_CURSOR_STATE_PRESSED = 0x04            // Hand completely pressed
        }

        public struct ImiHandCursorData
        {
            ImiHandType handType;                   // Left hand or right hand
            float cursorX;                  // Horizontal position(0.0~1.0), adjusted relative to interaction region(Upper left is origin point),-1 means invalid value
            float cursorY;                  // Vertical position(0.0~1.0), adjusted relative to interaction region(Upper left is origin point),-1 means invalid value
            float worldX;                       // Skeleton joint X position(mm) in world coordinate
            float worldY;                       // Skeleton joint Y position(mm) in world coordinate
            float worldZ;                       // Skeleton joint Z position(mm) in world coordinate
            float pressProgress;                // Progress(0.0~1.0) towards a push action,0.0 represents press origin and 1.0 represents pressed trigger point
            uint handCursorState;           // A combination of ImiHandCursorState flags
        }

        public enum ImiUserPositionFlag
        {
            IMI_USER_POSITION_FLAG_GOOD = 0x00,         // Position good
            IMI_USER_POSITION_FLAG_TOO_NEAR = 0x01,         // Too Near
            IMI_USER_POSITION_FLAG_TOO_FAR = 0x02,          // Too Far
            IMI_USER_POSITION_FLAG_TOO_LEFT = 0x04,         // Too Left
            IMI_USER_POSITION_FLAG_TOO_RIGHT = 0x08,            // Too Right
            IMI_USER_POSITION_FLAG_DARK_CLOSE_OR_INTERFERENCE = 0x10,           // Dark close or interference
            IMI_USER_POSITION_FLAG_RIGHT_HAND_TOO_HIGH = 0x20           // Right hand too high
        }

        public struct ImiGestureData
        {
            // Gesture recognition progress
            public float progress;
        }

        public struct ImiUserData
        {
            uint userID;                                        // User's ID(skeletonData.trackingID or skeletonData.userIndex)
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = IMI_USER_HANDCURSOR_COUNT)]
            ImiHandCursorData[] handCursorDatas;    // Hand cursor info array.	0-left hand  1-right hand
        }

        public struct ImiInteractionFrame
        {
            ImiUserData userData;                                   // User data
        }

        public struct ImiGestureEventArgs
        {
            public uint trackingID;
            public ImiGesturePro.GestureType gestureType;
            public ImiGestureData gestureData;
        }

        //[DllImport(filePath2, EntryPoint = "InitGesture")]
        //public static extern int ImiGestureInitialize();

        [DllImport(filePath, EntryPoint = "AddGesture")]
        public static extern int ImiAddGesture(uint userID, ImiGesturePro.GestureType gestureType, System.IntPtr gestureRecongnizedCallBack, System.IntPtr gestureRecongnizingCallBack);

        [DllImport(filePath, EntryPoint = "RemoveGesture")]
        public static extern int ImiRemoveGesture(uint userID, ImiGesturePro.GestureType gestureType);

        [DllImport(filePath, EntryPoint = "RemoveAllGestures")]
        public static extern int ImiRemoveAllGesture(uint userID);

        [DllImport(filePath, EntryPoint = "UpdateGesture")]
        public static extern int ImiUpdateGesture(uint userID, ref ImiWrapper.ImiSkeletonData skeletonData);

        [DllImport(filePath, EntryPoint = "GetNextInteractionFrame")]
        public static extern int ImiGetNextInteractionFrame(uint userID, ref ImiWrapper.ImiSkeletonData skeletonData, ref ImiInteractionFrame pInteractionFrame);

        [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
        public delegate void ImiGestureRecognizedCallBack(ImiGestureEventArgs s);

        [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
        public delegate void ImiGestureRecognizingCallBack(ImiGestureEventArgs s);

    }
}


